package com.linyu.mallchat.common.user.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.linyu.mallchat.common.user.dao.UserDao;
import com.linyu.mallchat.common.user.domain.entity.User;
import com.linyu.mallchat.common.user.service.UserService;
import com.linyu.mallchat.common.user.service.WXMsgService;
import com.linyu.mallchat.common.user.service.adapter.TextBuilder;
import com.linyu.mallchat.common.user.service.adapter.UserAdapter;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.net.URLEncoder;
import java.util.Date;
import java.util.Objects;

/**
 * 微信消息处理服务实现类
 */
@Slf4j
@Service
public class WXMsgServiceImpl implements WXMsgService {

    @Value("${wx.mp.callback}")
    private String callback;

    /**
     * 注意点：
     *    三个参数：1、appid；app 的 ID
     *            2、redirect_uri： 点击响应请求的路径 ---> 指向应用程序的回调地址，这个地址需要我们自己定义，并且要能接收到微信服务器的回调参数，（接口）
     *            3、scope：两种，这里选择第二种拿更多的数据，看文档：https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
     */
    public static final String URL= "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";

    @Autowired
    private UserDao userDao;

    @Autowired
    private UserService userService;

    @Autowired
    @Lazy
    private WxMpService wxMpService;

    /**
     * 用户扫码成功
     *
     * @return
     */
    @Override
    public WxMpXmlOutMessage scan(WxMpXmlMessage wxMpXmlMessage) {
        String openId = wxMpXmlMessage.getFromUser();
        Integer code = getEventKey(wxMpXmlMessage);
        if (Objects.isNull(code)){
            return null;
        }
        // 根据 openId 获取用户
        User user =userDao.getByOpenId(openId);
        boolean registered = Objects.nonNull(user);
        boolean authorized = registered && StrUtil.isNotBlank(user.getAvatar());
        // 用户已经注册并授权
        if (registered && authorized){
            // todo 走登录成功的逻辑，给前端推送消息，通过 code
        }
        // 用户未注册就先注册
        if (!registered){
            User newUser = UserAdapter.buildUserSave(openId);
            Long register = userService.register(newUser);
        }
        // 推送链接让用户授权
        String authorizeUrl = String.format(URL, wxMpService.getWxMpConfigStorage().getAppId(), URLEncoder.encode(callback + "/wx/portal/public/callBack"));
        return TextBuilder.build("请点击登录：<a href=\"" + authorizeUrl + "\">登录</a>" , wxMpXmlMessage);
    }

    /**
     * 用户授权成功：填入用户信息
     * @param userInfo 用户信息
     */
    @Override
    public void authorize(WxOAuth2UserInfo userInfo) {
        userDao.lambdaUpdate()
                .set(User::getName, userInfo.getNickname())
                .set(User::getSex, userInfo.getSex())
                .set(User::getAvatar, userInfo.getHeadImgUrl())
                .set(User::getUpdateTime, LocalDateTimeUtil.now())
                .eq(User::getOpenId, userInfo.getOpenid())
                .update();
    }

    /**
     * 获取二维码携带的参数
     */
    private Integer getEventKey(WxMpXmlMessage wxMpXmlMessage) {
        try {
            String eventKey = wxMpXmlMessage.getEventKey();
            String code = eventKey.replace("qrscene_", "");
            return Integer.parseInt(code);
        }catch (Exception e){
            log.error("getEventKey error eventKey:{}", wxMpXmlMessage.getEventKey(), e);
            return null;
        }
    }
}
